#ifndef B_PHYSICS_ENGINE_H_
#define B_PHYSICS_ENGINE_H_

#include <btBulletDynamicsCommon.h>
#include "LineDrawer.h"
#include "BPhysicsMotionState.h"
#include "BPhysicsActor.h"
#include <map>

typedef btAlignedObjectArray<BPhysicsActor*> vActors;
typedef std::map<btRigidBody*, BPhysicsActor*> ActorMap;

/* This class is a wrapper around Bullet physics,
   It manages all Actors, and has support functions for
   the creation of several specific types of actor
   (vehicles, AI agents, etc) 

   This could be a singleton, but as it is owned by Engine::Instance(),
   it is available throughout the code with ()->GetEngine().
*/
class BPhysicsEngine
{
public:
    BPhysicsEngine();
public:
    /* Get funtionality */
    ActorMap& GetActorMap(){return m_actorMap;}
    LineDrawer* GetDebugDrawer(){return m_debugDrawer;}
    btDynamicsWorld* GetWorld(){return m_dynamicsWorld;}
    btVector3 GetClickDirection();
    vActors& GetActors();

    /* Main functionailty */
    void Update(int dt);
    void Release();
    void Initialize(const D3DXVECTOR3& Gravity);
    void AddActor(BPhysicsActor* actor);
    void DrawDebug();
    /* Helper functions */
    void CleanActors();
    bool IsInitialised() const { return m_initialised; }
    void RemoveVehicle( btRaycastVehicle* v );
    void SetDebugDrawMode( int param1 );
    void CallUpdateGrid();
    void DisableBody( BPhysicsActor* m_vehicle );
    void EnableBody(BPhysicsActor* m_vehicle );
    /* Internal use */
    void AddCollisionShape(btCollisionShape* shape);

    /* Deformable meshes and right Click ray-cast forces */
    //1000 - 10000 good value
    void ApplyPushForce( float param1 );
    //0.11f is a good amount
    void ApplyDentingForce(float amount);
    //amountScale 0.95f is good
    void CollisionDentingForce(float amountMove, float amountScale, int triIndex, const btVector3& direction, BPhysicsActor* actor);
    // 0.9f is OK
    void ApplyScaleTriForce(float amount, int triIndex, BPhysicsActor* actor);
    BPhysicsActor* PickActor();
    BPhysicsActor* SearchForActor(btRigidBody* body);
    bool RayTest(const btVector3& rayFrom,const btVector3& rayTo, btCollisionWorld::ClosestRayResultCallback& rayCallback);
private:
    ///this is the most important class
    btDynamicsWorld*		m_dynamicsWorld;
    //these are the support classes for the DynamicsWorld
    btBroadphaseInterface*	m_broadphase;
    btCollisionDispatcher*	m_dispatcher;
    btConstraintSolver*	m_solver;
    btDefaultCollisionConfiguration* m_collisionConfiguration;
    //keep the collision shapes, for deletion/cleanup
    btAlignedObjectArray<btCollisionShape*>	m_collisionShapes;
    //this draws the debug data called in ->debugDrawWorld();
    LineDrawer* m_debugDrawer;
    //So we can do stuff once,
    bool m_initialised;
    /* So that we can work with actors when the engine gives us bodies */
    ActorMap m_actorMap;
    vActors m_actors;
};


#endif